#include "tracexportprojectselectwidget.h"
#include "ui_tracexportprojectselectwidget.h"
#include "tracsettings.h"

#include "xmlrpcbase64.h"
#include "xmlrpcconnection.h"
#include "xmlrpcparser.h"
#include "xmlrpcrequest.h"
#include "xmlrpcresponse.h"

#include <QtGui/QFileDialog>
#include <QtGui/QMessageBox>
#include <QtCore/QUrl>
#include <QtCore/QDebug>

using XmlRpc::XmlRpcConnection;
using XmlRpc::XmlRpcRequest;
using XmlRpc::XmlRpcBase64;

namespace Trac {
namespace Internal {

TracExportProjectSelectWidget::TracExportProjectSelectWidget(QWidget *parent) :
    QWidget(parent),
    ui(new Ui::TracExportProjectSelectWidget()),
    m_valid(false),
    m_connection(new XmlRpcConnection(this)),
    m_XmlRpcError(false)
{

    ui->setupUi(this);
    setMinimumWidth(600);
    setMinimumHeight(100);

    QPalette palette;
    palette.setColor(QPalette::WindowText, Qt::red);

    ui->nameErrorLabel->setVisible(false);
    ui->nameErrorLabel->setPalette(palette);
    ui->identifierErrorLabel->setVisible(false);
    ui->identifierErrorLabel->setPalette(palette);
    ui->descriptionErrorLabel->setText(Constants::ERRORSTRING_PROJECTDESCRIPTION);
    ui->descriptionErrorLabel->setVisible(false);
    ui->descriptionErrorLabel->setPalette(palette);

    connect(ui->browsePushButton, SIGNAL(clicked()),
            this, SLOT(browse()));
    connect(m_connection, SIGNAL(finished(XmlRpc::XmlRpcResponse*)),
            this, SLOT(rpcQueryCompleted(XmlRpc::XmlRpcResponse*)));
    connect(this, SIGNAL(errorChanged(bool)),
            this, SLOT(handleError(bool)));
    connect(ui->selectProjectComboBox, SIGNAL(currentIndexChanged(int)),
            this, SLOT(checkIsValid()));
    connect(ui->nameLineEdit, SIGNAL(textChanged(QString)),
            this, SLOT(checkIsValid()));
    connect(ui->identifierLineEdit, SIGNAL(textChanged(QString)),
            this, SLOT(checkIsValid()));
    connect(ui->descriptionTextEdit, SIGNAL(textChanged()),
            this, SLOT(checkIsValid()));
}

TracExportProjectSelectWidget::~TracExportProjectSelectWidget()
{
    delete ui;
}

bool TracExportProjectSelectWidget::isValid() const
{
    return m_valid;
}

const QString TracExportProjectSelectWidget::connectionUrl()
{
    return m_connection->url().toString();
}

void TracExportProjectSelectWidget::initialize()
{
    ui->selectProjectComboBox->setEnabled(true);
    ui->browsePushButton->setEnabled(true);
    ui->nameLineEdit->setEnabled(true);
    ui->identifierLineEdit->setEnabled(true);
    ui->descriptionTextEdit->setEnabled(true);
    m_connection->setUrl(QUrl(TracSettings::instance()->hostName()));
    m_projectData.clear();
    ui->selectProjectComboBox->setCurrentIndex(-1);
    ui->nameLineEdit->clear();
    ui->identifierLineEdit->clear();
    ui->descriptionTextEdit->clear();
}

void TracExportProjectSelectWidget::browse()
{

    QString newProjectFile = QFileDialog::getOpenFileName(this,                
                                                          tr("Browse a project file"),
                                                          TracSettings::instance()->workingPath(),
                                                          tr("Qt Creator Project Files (*.pro)"));

    if(!newProjectFile.isEmpty()) {
        ui->selectProjectComboBox->addItem(newProjectFile);
        ui->selectProjectComboBox->setCurrentIndex(ui->selectProjectComboBox->count() - 1);
    }
}

void TracExportProjectSelectWidget::requestProjects()
{
    QVariantList parameters;

    parameters << "" << "";
    m_request.setMethod(Constants::RPC_SEARCHPROJECTS);
    m_request.setParams(parameters);
    m_connection->query(m_request);
}

void TracExportProjectSelectWidget::rpcQueryCompleted(XmlRpc::XmlRpcResponse *response)
{

    if(response->error()) {

        QString errorString;
        QMessageBox errorMsgBox;

        errorString = QString(tr("ERROR (%1): %2")).arg(response->errorCode())
                      .arg(response->errorString());

        errorMsgBox.setText("XmlRpc error");
        errorMsgBox.setInformativeText(errorString);
        errorMsgBox.setStandardButtons(QMessageBox::Ok);
        errorMsgBox.setDefaultButton(QMessageBox::Ok);
        errorMsgBox.exec();

        if(m_XmlRpcError == false) {
            m_XmlRpcError = true;
            emit errorChanged(m_XmlRpcError);
        }

    }
    else {
        if(m_XmlRpcError == true) {
            m_XmlRpcError = false;
            emit errorChanged(m_XmlRpcError);
        }


        QVariantList values = response->returnValue().toList();

        if(response->methodCalled() == Constants::RPC_SEARCHPROJECTS && values.count() > 0) {
            populateProjectData(values);
        }
    }
    response->deleteLater();
}

void TracExportProjectSelectWidget::handleError(bool value)
{
    ui->selectProjectComboBox->setEnabled(!value);
    ui->browsePushButton->setEnabled(!value);
    ui->nameLineEdit->setEnabled(!value);
    ui->identifierLineEdit->setEnabled(!value);
    ui->descriptionTextEdit->setEnabled(!value);
}

void TracExportProjectSelectWidget::checkIsValid()
{
    bool projectComboBoxIsValid = validateSelectProjectComboBox(); //(ui->selectProjectComboBox->currentIndex() != -1);
    bool nameLineEditIsValid = validateNameLineEdit();
    bool identifierLineEditIsValid = validateIdentifierLineEdit();
    bool descriptionTextEditIsValid = validateDescriptionTextEdit();

    if(projectComboBoxIsValid
       && nameLineEditIsValid
        && identifierLineEditIsValid
        && descriptionTextEditIsValid) {

        if(m_valid == false) {
            m_valid = true;
            emit (validChanged(m_valid));
        }

    }
    else {
        if(m_valid == true) {
            m_valid = false;
            emit (validChanged(m_valid));
        }
    }
}

void TracExportProjectSelectWidget::populateProjectData(QVariantList values)
{
    QVariant project;
    ProjectData projectData;

    for(int i = 0; i < values.count(); i++) {
        project = values[i];

        projectData.name = project.toString().remove(0, project.toString().indexOf("|") + 1);
        projectData.identifier = project.toString().left(project.toString().indexOf("|"));

        m_projectData.insert(i, projectData);
    }

}

bool TracExportProjectSelectWidget::validateSelectProjectComboBox()
{
    if(ui->selectProjectComboBox->currentIndex() != -1) {

        if(ui->selectProjectComboBox->currentText().contains('/')) {
            TracSettings::instance()->setWorkingPath(ui->selectProjectComboBox->currentText().left(ui->selectProjectComboBox->currentText().lastIndexOf('/')));
        }
        return true;
    }
    else
        return false;
}

bool TracExportProjectSelectWidget::validateNameLineEdit()
{
    bool error = false;
    QPalette palette;

    if(!ui->nameLineEdit->text().isEmpty()) {
        if(ui->nameLineEdit->text().length() < 2) {
            error = true;
            ui->nameErrorLabel->setText(Constants::ERRORSTRING_PROJECTNAMETOOSHORT);
        }
        else {
            for(int i = 0; i < m_projectData.count() && error == false; i++) {
                if(m_projectData.value(i).name == ui->nameLineEdit->text()) {
                    error = true;
                    ui->nameErrorLabel->setText(Constants::ERRORSTRING_PROJECTNAMEEXISTS);
                }
            }
        }

        if(error) {
            palette.setColor(QPalette::Text, Qt::red);
        }
        else {
            palette.setColor(QPalette::Text, Qt::black);
            TracSettings::instance()->setProjectName(ui->nameLineEdit->text());
        }

        ui->nameLineEdit->setPalette(palette);
        ui->nameErrorLabel->setVisible(error);
        return !error;
    }
    else {
        palette.setColor(QPalette::Text, Qt::black);
        ui->nameLineEdit->setPalette(palette);
        ui->nameErrorLabel->setVisible(error);
        return error;
    }

}

bool TracExportProjectSelectWidget::validateIdentifierLineEdit()
{
    bool error = false;
    QPalette palette;

    if(!ui->identifierLineEdit->text().isEmpty()) {
        if(ui->identifierLineEdit->text().length() > 32) {
            error = true;
            ui->identifierErrorLabel->setText(Constants::ERRORSTRING_PROJECTIDENTIFIERTOOLONG);
        }
        else {
            for(int i = 0; i < m_projectData.count() && error == false; i++) {
                if(m_projectData.value(i).identifier == ui->identifierLineEdit->text()) {
                    error = true;
                    ui->identifierErrorLabel->setText(Constants::ERRORSTRING_PROJECTIDENTIFIEREXISTS);
                }
            }
        }

        if(error) {
            palette.setColor(QPalette::Text, Qt::red);
        }
        else {
            palette.setColor(QPalette::Text, Qt::black);
            TracSettings::instance()->setProjectIdentifier(ui->identifierLineEdit->text());
        }

        ui->identifierLineEdit->setPalette(palette);
        ui->identifierErrorLabel->setVisible(error);
        return !error;
    }
    else {
        palette.setColor(QPalette::Text, Qt::black);
        ui->identifierLineEdit->setPalette(palette);
        ui->identifierErrorLabel->setVisible(error);
        return error;
    }

}

bool TracExportProjectSelectWidget::validateDescriptionTextEdit()
{
    QPalette palette;

    if(!ui->descriptionTextEdit->document()->isEmpty()) {

        if(ui->descriptionTextEdit->document()->toPlainText().length() < 8) {
            palette.setColor(QPalette::Text, Qt::red);
            ui->descriptionTextEdit->setPalette(palette);
            ui->descriptionErrorLabel->setVisible(true);
            return false;
        }
        else {
            TracSettings::instance()->setProjectDescription(ui->descriptionTextEdit->document()->toPlainText());
            palette.setColor(QPalette::Text, Qt::black);
            ui->descriptionTextEdit->setPalette(palette);
            ui->descriptionErrorLabel->setVisible(false);
            return true;
        }

    }
    else {
        palette.setColor(QPalette::Text, Qt::black);
        ui->descriptionTextEdit->setPalette(palette);
        ui->descriptionErrorLabel->setVisible(false);
        return false;
    }

}

} // namespace Internal
} // namespace Trac
